/*
 * To change this template, choose Tools | Templates
 * and open the template in the editor.
 */
package fr.vod.gauss.matrice;

import fr.vod.gauss.operations.Operation;

/**
 * 
 * @author drazanakoto
 */
public class PivotDeGaussImpl extends PivotDeGauss {

	/**
	 * 
	 * @param op
	 */
	public PivotDeGaussImpl(Operation op) {
		super(op);
	}

	@Override
	public boolean resoudre(Matrice m) {
		/**
         *
         */
		if (m.getLength() == 0) {
			return false;
		}

		/**
		 * triangulisation inférieur
		 */
		for (int i = 0; i < m.getLength(); i++) {

			/**
             *
             */
			if (!getPivot(i, m)) {
				return false;
			}

			/**
			 * mettre la diognal est à 1
			 */
			mettreDiagonalUn(i, m.get(i));

			/**
			 * mettre le colonne du pivot à zéro
			 */
			for (int j = i + 1; j < m.getLength(); j++) {
				eliminer(i, m.get(i), m.get(j));
			}
		}

		// verifier tout les diagonal est égal à 1 diagonal et retourné faux
		// dans le cas contraire
		for (int i = 0; i < m.getLength(); i++) {
			if (m.get(i).get(i) != 1) {
				return false;
			}
		}

		// triangulisation supérieur
		for (int i = m.getLength() - 1; i > -1; i--) {
			/**
			 * mettre le colonne du pivot à zéro
			 */
			for (int j = i - 1; j > -1; j--) {
				eliminer(i, m.get(i), m.get(j));
			}
		}
		return true;
	}

	/**
	 * 
	 * @param indice
	 * @param e
	 */
	protected void mettreDiagonalUn(int indice, Equation e) {
		int diagonal = e.get(indice);
		if (diagonal != 1) {
			for (int i = 0; i < e.getSize(); i++) {
				e.setValueAt(i, op.division(e.get(i), diagonal));
			}
			e.setResult(op.division(e.getResult(), diagonal));
		}
	}

	/**
	 * 
	 * @param c
	 * @param pivot
	 * @param l
	 */
	protected void eliminer(int c, Equation pivot, Equation l) {
		int tmp = l.get(c);
		if (tmp != 0) {
			for (int i = 0; i < pivot.getSize(); i++) {
				l.setValueAt(
						i,
						op.soustraction(l.get(i),
								op.multiplication(pivot.get(i), tmp)));

			}
			l.setResult(op.soustraction(l.getResult(),
					op.multiplication(pivot.getResult(), tmp)));
		}
	}

	/**
	 * 
	 * @param col
	 * @param m
	 * @return
	 */
	protected boolean getPivot(int col, Matrice m) {
		int next = col;
		Equation tmp = m.get(next);

		while (tmp.get(col) == 0 && next < m.getLength()) {
			if (equationNull(next + 1, tmp)) {
				m.remove(next);
				return false;
			}
			next++;
			if (next < m.getLength()) {
				tmp = m.get(next);
			} else {
				return false;
			}
		}

		/**
         *
         */
		if (col != next) {
			m.move(next, col);
		}
		return true;
	}

	/**
	 * 
	 * @param p
	 * @param m
	 * @return
	 */
	protected boolean equationNull(int p, Equation m) {
		for (int i = p; i < m.getSize(); i++) {
			if (m.get(i) != 0) {
				return false;
			}
		}
		return true;
	}
}
